function Person(name) {
  this.name = name;
}
Person.prototype.walk = function () {
  console.log(this.name, "is walking");
};
Person.make = function () {
  console.log(this.name, "making");
};

function Student(name, level) {
  Person.call(this, name);
  this.level = level;
}

// (function () {//方式0
//   Student.prototype.__proto__ = Person.prototype;
// })();
// (function () {//方式一
//   Object.setPrototypeOf(Student.prototype, Person.prototype);
// })();
// (function () {//方式二
//   Student.prototype = Object.create(Person.prototype);
//   Student.prototype.constructor = Student;
//   Student.__proto__ = Person;
// })();

(function () {
  //方式三
  const obj = function () { };
  obj.prototype = Person.prototype;
  Student.prototype = new obj();
  Student.prototype.constructor = Student;
  Student.__proto__ = Person;
})();

var p = new Person("eric");
var s = new Student("peter", 3);

s.walk();
console.log(p, s);
console.log(p instanceof Person);
console.log(p instanceof Student);
console.log(s instanceof Student);
console.log(s instanceof Person);

console.log(Student.prototype.constructor === Student);


// 问：什么是原型链？
// 答：JS里每个对象都有一个原型，在chrome浏览器里可以认为是属性 __proto__，指向的是这个对象的构造函数的 prototype 属性（在JS里函数也是对象的一种所以可以有属性）。
//     而这个原型也是一个对象，那作为对象，它又有一个原型，又是对象，又有原型，如此说来似乎子子孙孙无穷尽也。然鹅事实并非如此。
//     举例，let a = {}，则 a.__proto__ === Object.prototype，因为 a 作为一个字面量对象，构造函数是 Object()，则 属性 a.__proto__ 指向构造函数 Object.prototype，容易理解。
//     然鹅，a.__proto__.__proto__ === null，就成立了，为何？不是说 a.__proto__ 是 Object.prototype 对象吗？既然是对象，那构造函数应当还是 Object，
//     那么 a.__proto__.__proto__ 就应该还是指向 Object.prototype 才对，为什么不是呢？
//     说到底，JS为什么要设计这么一套原型和原型链体系？是为了实现继承！是为了聚合公用的共有的属性和方法。不是为了原型而原型。具体的说，是为了当通过对象 a 访问其属性 xxx 或者方法 xxx 时，
//     如果 a 本身没有此方法/属性，则去 a.__proto__ 里找，如果还不存在，则到 a.__proto__.__proto__ 里找，既然是要找，那么说明肯定不是大海捞针，肯定需要找的范围是可以预见的，确定的。
//     所以，如果 a 是普通字面量对象，那么 a.__proto__.__proto__ 就需要是null了。
//     想想如果不是如此会怎样，如果 a.__proto__.__proto__ === a.__proto__ === Object.prototype，那么当 a 里不包含 xxx 属性/方法时，到 a.__proto__ 里找，还找不到则到 a.__proto__.__proto__里找，
//     然鹅，a.__proto__ 和 a.__proto__.__proto__ 是同一个东西，相当于你在一间房子里找一只袜子找了一遍，没找到，又找了一遍，看起来还要再找一遍而且会不停的找下去不停的找不到，你完了。
//     所以，JS里和对象相关的公共的属性/方法，就都放在 Object.prototype 里了，它是一个特殊的对象，它的 __proto__ 是 null。所以 a.__proto__.__proto__ === null。